/*HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
 H	sc2sim.h
 H	Application name: SC-2 (lite) simulation
 H	Programmers names:
 H	Date completed: 3/9/11
 H	Brief Description: Header file for the sc2sim application.  This application simulates a
 H	subset of the SC-2's ISA.  It uses the register, register file, and ALU ADT's that we've
 H	developed so far to simulate the CPU's physical components.
 H
 HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH*/

#ifndef BOOLEAN
#define BOOLEAN unsigned char
#define TRUE 1
#define FALSE 0
#endif

/*#################################################################################################
 # Error Code bit-flags (collected from all the ADT's)
 ##################################################################################################*/
#define ERROR_MEM_OUT_OF_RANGE 		0x1
#define NULL_ERR 			0x2
#define REG_NOT_FOUND_ERR 		0x4
#define OP_OUT_OF_RANGE_ERR 		0x8
#define ALU_DIVIDE_BY_ZERO 		0x10
#define PROGRAM_HALT			0x20
#define INCORRECT_OPERAND_ERR		0x40
#define INVALID_PORT_ERR    0x80




//The below are needed to avoid multiple file compilation
/***************************************************************************************************
 * 	ADT: Register 16
 * 	Description: A register is a 16 bit variable type implemented as an unsigned short.
 *
 ***************************************************************************************************/

/*#################################################################################################
 # Defines
 ##################################################################################################*/
#define uchar 				unsigned char
#define ushort 				unsigned short
#define MAX_USHORT          0xFFFF
#define LOB_MASK 			0x00FF
#define HOB_MASK 			0xFF00
#define BIT_15 				0x8000

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 $ Typedefs
 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
typedef ushort Register;
typedef Register * RegisterPtr;

/*-------------------------------------------------------------------------------------------------
 - Prototypes
 - Basic operations
 -      Initialize: creates register object and puts a random value from 0 to 65535 into it.
 -      GetLowByte: returns an unsigned char (uchar) from LOB of register
 -      GetHIByte:  returns a uchar from the HOB of register
 -      PutLowByte: puts a uchar into the LOB of the register
 -      PutHIByte:  puts a uchar into the HOB of the register
 -      SignOf:     returns bit 15 value in a uchar
 -      Destructor: not needed
 - Composite Operations
 -      GetRegValue: returns a ushort, the value in the register
 -      PutRegValue: returns error, puts ushort into register
 ---------------------------------------------------------------------------------------------------*/
RegisterPtr register_initialize(void); //allocates space and returns pointer
uchar register_getLowByte(RegisterPtr, int *); //returns LOB if successful
uchar register_getHiByte(RegisterPtr, int *); //returns HOB if successful
int register_putLowByte(RegisterPtr, uchar); //returns error code
int register_putHiByte(RegisterPtr, uchar); //returns error code
uchar register_signOf(RegisterPtr); //returns 0, 1, 2 or greater error code
ushort register_getRegValue(RegisterPtr, int *);
int register_putRegValue(RegisterPtr, ushort);




/***************************************************************************************************
 * 	ADT: SC-2 Register File (uses Register)
 * 	Description: The register file is a set of sixteen 16-bit registers as described in the SC-2
 *	document
 *
 ***************************************************************************************************/

/*#################################################################################################
 # Defines
 ##################################################################################################*/
#define REGISTER_COUNT 16
#define R0 (uchar) 0
#define R1 (uchar) 1
#define R2 (uchar) 2
#define R3 (uchar) 3
#define R4 (uchar) 4
#define R5 (uchar) 5
#define R6 (uchar) 6
#define R7 (uchar) 7
#define R8 (uchar) 8
#define R9 (uchar) 9
#define RA (uchar) 0xA
#define RB (uchar) 0xB
#define RC (uchar) 0xC
#define RD (uchar) 0xD
#define RE (uchar) 0xE
#define RF (uchar) 0xF
#define LOB_WHICH 0
#define HOB_WHICH 1

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 $ Typedefs
 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
typedef RegisterPtr * RegisterFilePtr;

/*-------------------------------------------------------------------------------------------------
 - Prototypes
 - Basic Operations
 -      Initialize: creates a register file of 16 Register objects in an array
 -      GetByteFrom: returns a uchar from a designated register and LOB or HOB
 -      PutByteTo:   puts a single byte to either LOB or HOB or register
 -      Destructor: not needed
 -      Composite Operations
 -      GetWordFrom: returns a ushort, the content of the designated register
 -      PutWordTo: puts the ushort into the designated register
 --------------------------------------------------------------------------------------------------*/
RegisterFilePtr registerFile_initialize(); //allocates space for 16 register pointers and calls register_initialize for each slot
uchar registerFile_getByteFrom(RegisterFilePtr, uchar, uchar, int *); //returns the byte in register reg_num and HOB or LOB indicated
                                                                      //by which, sets error code
int registerFile_putByteTo(RegisterFilePtr, uchar, uchar, uchar); //puts the byte into the reg_num and HOB or LOB indicated by which
                                                                  //returns error code
ushort registerFile_getRegValue(RegisterFilePtr, uchar, int *); //returns the register content; sets error code
int registerFile_putRegValue(RegisterFilePtr, uchar, ushort); //puts the value into the designated reg_num register; returns error code

/***************************************************************************************************
 * 	ADT: SC-2 Internal Registers (uses Register)
 * 	Description: The internal registers are a set of specialized registers that exists inside the CPU
 *
 ***************************************************************************************************/

/*#################################################################################################
 # Defines
 ##################################################################################################*/


/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 $ Typedefs
 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
typedef struct internal_registers_str
    {
        RegisterPtr pc;
        RegisterPtr ir;
        RegisterPtr sw;

        BOOLEAN halt_bit;
    } InternalRegistersStr;

typedef InternalRegistersStr * InternalRegisters;

/*-------------------------------------------------------------------------------------------------
 - Prototypes
 - Basic Operations
 -      Initialize: Allocates memory for an InternalRegistersStr and returns pointer.
 -      Set PC: Sets the address pointed to by the PC register.
 -      Get PC: Returns the current value of the PC register.
 -      Set IR: Sets the instruction contained in the IR register.
 -      Get IR: Returns the current value of the IR register.
 -      Set SW: Sets the status word contained in the SW register.
 -      Get SW: Returns the current value of the SW register.
 -      Set Halt: Sets the halt bit to the specified value (TRUE or FALSE).
 -      Check Halt: Returns the current value of the halt bit.
 -      Destructor: not needed
 --------------------------------------------------------------------------------------------------*/
InternalRegisters internalRegisters_initialize(); //Allocates memory for an InternalRegistersStr and returns pointer.
int internalRegisters_setPC(InternalRegisters, ushort); //Sets the value of the PC register.
ushort internalRegisters_getPC(InternalRegisters, int *); //Returns the current value of the PC register. Sets error code.
int internalRegisters_setIR(InternalRegisters, ushort); //Sets the instruction contained in the IR register.
ushort internalRegisters_getIR(InternalRegisters, int *); //Returns the current value of the IR register. Sets error code.
int internalRegisters_setSW(InternalRegisters, ushort); //Sets the status word contained in the SW register.
ushort internalRegisters_getSW(InternalRegisters, int *); //Returns the current value of the SW register. Sets error code.
int internalRegisters_setHalt(InternalRegisters, BOOLEAN);	// sets halt_bit (TRUE or FALSE) and returns error code.
BOOLEAN internalRegisters_checkHalt(InternalRegisters, int*);	// returns status of halt_bit and sets error code.



 /***************************************************************************************************
 * 	ADT: ALU
 * 	Description: ALU simulation for the SC-2 (uses 'Register16' and 'SC-2 RegisterFile')
 *
 ***************************************************************************************************/

/*#################################################################################################
 # Defines
 ##################################################################################################*/
// op_sel values for ALU operations
#define OP_ADD		0x00
#define OP_SUB		0x01
#define OP_MUL		0x02
#define OP_DIV		0x03
#define OP_NEG		0x04
#define OP_AND		0x05
#define OP_OR		0x06
#define OP_XOR		0x07
#define OP_NOT		0x08
#define OP_SHL		0x09
#define OP_SHR		0x0A

// values of the status bits within the SW register.
#define SW_CLEAR_STATUS	0x0FFF
#define SW_N_BIT	0x8000
#define SW_Z_BIT	0x4000
#define SW_C_BIT	0x2000
#define SW_O_BIT	0x1000

//bit masks
#define REG16_MASK 0xFFFF
#define BIT_15 0x8000
#define HOW_MASK 0xFFFF0000
#define LOW_MASK 0x0000FFFF

//carry detect
#define MAX_USHORT 0xFFFF
#define MAX_SIGNED_SHORT 0x7FFF
#define MIN_SIGNED_SHORT 0x8000

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 $ Typedefs
 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
typedef struct alu_str
	{
		RegisterPtr A;		//	A - input (operand 1)
		RegisterPtr B;		//	B - input (operand 2)
		RegisterPtr C;		//	C - output
		uchar op_sel;		//	operation select

	} ALUStr;

typedef ALUStr * ALU;

/*-------------------------------------------------------------------------------------------------
 - Prototypes
 - Basic Operations:
 -		Initialize:  Creates ALU object
 -		Execute:   Simulates a clock signal, causing the selected operation to execute.
 -
 -	'External' Operations
 -		Load A:  Simulates the state of the A register as LdA is
 -				enabled by explicitly loading an operand into A
 -
 -		Load B:  Simulates the state of the B register as LdB is
 -				enabled by explicitly loading an operand into B
 -
 -		Select Operation:  Simulates the op_sel signal by loading a
 -				value into the op_sel register
 -
 -		Set Status:  	Sets the relevant bit in SW
 -
 -		Read Output C:  Simulates the state of the data bus as DrALU is
 -				enabled by explicitly reading the value of C
 -
 -	'Internal' Operations:
 -		Addition:  	C <- A + B, set status
 -		Subtraction:  	C <- A - B, set status
 -		Multiplication: $R8 <- (low-order) A * B, set status
 -				$R9 <- (high-order) A * B, set status
 -		Division: 	$RA <- (quotient) A / B, set status
 -				$RB <- (remainder) A / B, set status
 -		Negation:  	C <- ~A + 1 (2's complement), set status
 -		AND:		C <- A & B, set status
 -		OR:		C <- A | B, set status
 -		XOR:		C <- A ^ B (bitwise XOR), set status
 -		NOT:		C <- ~A, set status
 -		Shift Left:	C <- A * 2, set status
 -		Shift Right: 	C <- A / 2, set status
 -
 -
 --------------------------------------------------------------------------------------------------*/
ALU	ALU_initialize();					// allocate ALU
int	ALU_execute(ALU, RegisterFilePtr, RegisterPtr);		// execute the selected operation on A&B
int	ALU_loadA(ALU, ushort);					// load ALU reg A with value
int 	ALU_loadB(ALU, ushort);					// load ALU reg B with value
int 	ALU_selectOperation(ALU, uchar);			// select operation to be performed
int	ALU_setStatusWord(ALU, RegisterFilePtr, RegisterPtr);	// update NZCO bits of SW.
ushort	ALU_readC(ALU, int*);					// return value in ALU reg C
int	ALU_add(ALU);						// C <- A + B
int 	ALU_subtract(ALU);					// C <- A - B
int 	ALU_multiply(ALU, RegisterFilePtr);			// needs address of regfile $R8 <- (low-order) A * B
								// 			    $R9 <- (high-order) A * B
int	ALU_divide(ALU, RegisterFilePtr);			// needs address of regfile $RA <- (quotient) A / B
								// 			    $RB <- (remainder) A / B
int	ALU_negate(ALU);					// C <- ~A + 1 (2's complement)
int 	ALU_and(ALU);						// C <- A & B
int 	ALU_or(ALU);						// C <- A | B
int 	ALU_xor(ALU);						// C <- A ^ B
int 	ALU_not(ALU);						// C <- ~A
int 	ALU_shiftLeft(ALU);					// C <- A * 2
int 	ALU_shiftRight(ALU);					// C <- A / 2




/*****************************************************************************************************
 *	ADT:  Memory Module
 *	Description:  The memory module simulates the SC-2 memory model starting at location
 *	0x3000 (user memory) to 0xFFFF. The memory is byte-addressable.
 *
 ****************************************************************************************************/

/*##################################################################################################
 # 	Defines
 ##################################################################################################*/
#define MEM_SIZE 0xCFFF
#define MEM_FIRST 0x3000
#define MEM_LAST 0xFFFF

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 $ 	Typedefs
 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
typedef uchar* MemoryModulePtr; // note we can skip an ADT for a memory slot!

/*--------------------------------------------------------------------------------------------------
 -  	Prototypes
 -  	Descriptions of public functions (in this simulation everything is basically public)
 -
 -	Basic Operations
 -		Initialize: allocates space for memory of uchar(s), fills memory with random values
 -				between 0 and 0xFF
 -		FetchByteFrom: returns a single uchar from location indicated
 -		StoreByteTo: puts a uchar into the memory location indicated
 -		Destructor: not needed
 -
 -	Composite Operations
 -		FetchWordFrom: returns a ushort (word) from the memory location indicated
 -		StoreWordTo: puts a ushort into consecutive memory locations starting with address given
 -
 --------------------------------------------------------------------------------------------------*/
// Basic Operations
MemoryModulePtr memory_initialize(); 				// creates user memory space and
								// fills with random numbers
uchar memory_fetchByteFrom(MemoryModulePtr, ushort, int*);	// returns a byte form address,
								// sets error code
int memory_storeByteTo(MemoryModulePtr, ushort, uchar); 	// stores byte at address,
								// sets error code

// Composite Operations
ushort memory_fetchWordFrom(MemoryModulePtr, ushort, int*);	// returns the contents of two
								// consecutive locations starting
								// at address. sets error code
int memory_storeWordTo(MemoryModulePtr, ushort, ushort); 	// stores word at address,
								// sets error code



/***************************************************************************************************
 * 	ADT: Input / Output
 * 	Description: Input / Output simulation for the SC-2. Simplified version has only video and
 *       keyboard defined.
 *
 ***************************************************************************************************/

/*##################################################################################################
 # 	Defines
 ##################################################################################################*/
#define KBD     (ushort) 0x0001
#define VID 	(ushort) 0x0002

#define MAX_UCHAR (uchar) 0xFF

 /*--------------------------------------------------------------------------------------------------
 -  	Prototypes
 -
 -  Basic Operations:
 -		Input: Retrieves a uchar from selected port.
 -		Output: Stores uchar to selected port.
 -
 --------------------------------------------------------------------------------------------------*/
 uchar io_input(ushort, int *);	//Retrieves a byte from selected port and sets error code.
                                            //NOTE: SC-2 has 2048 ports which would have to be addressed as
                                            //A ushort.
 int io_output(ushort, uchar); //Stores byte to selected port and returns error code





/***************************************************************************************************
 * 	ADT: Controller
 * 	Description: Controller simulation for the SC-2 -- a finite state machine that cycles
 *		through Fetch,	Decode,	and Execute states, testing for an asserted Halt Bit at the
 *		end of each cycle.
 *
 ***************************************************************************************************/

/*##################################################################################################
 # 	Defines
 ##################################################################################################*/
#define FETCH 	0x00
#define DECODE 	0x01
#define EXECUTE 0x02

#define OPCODE_FILTER	0xF800
#define OPCODE_SHIFT	0x0800		// divide to bring opcode to low bits
#define OPERAND1_FILTER	0x0780
#define OPERAND1_SHIFT	0x0080		// divide to bring operand 1 to low bits
#define OPERAND2_FILTER	0x0078
#define OPERAND2_SHIFT	0x0008		// divide to bring operand 2 to low bits
#define OPERAND3_FILTER	0x0007
#define IMMED7_FILTER	0x007F
#define IMMED11_FILTER	0x07FF		// (although you could just !OPCODE_FILTER)

#define OPCODE_LDI	0x01		// format 0
#define OPCODE_LADR	0x15		// format 5
#define OPCODE_LDB	0x02		// format 1 (register relative)
#define OPCODE_LDW	0x03		// format 1 (register relative)
#define OPCODE_STB	0x06		// format 1 (register relative)
#define OPCODE_STW	0x07		// format 1 (register relative)
#define OPCODE_MOVB	0x02		// format 1 (same as LDB, with AMOD = 0x04)
#define OPCODE_MOVW	0x03		// format 1 (same as LDW, with AMOD = 0x05)
#define OPCODE_ADDI	0x08		// format 0
#define OPCODE_ADD	0x0A		// format 4
#define OPCODE_SUBI	0x09		// format 0
#define OPCODE_SUB	0x0B		// format 4
#define OPCODE_NEG	0x11		// format 5
#define OPCODE_AND	0x0E		// format 4
#define OPCODE_OR	0x0F		// format 4
#define OPCODE_NOT	0x12		// format 5
#define OPCODE_SHL	0x1E		// format 1
#define OPCODE_SHR	0x1E		// format 1
#define OPCODE_BR	0x13		// format 3
#define OPCODE_BRCC	0x14		// format 3 - possibly x13??
#define OPCODE_IN	0x18		// format 6
#define OPCODE_OUT	0x19		// format 6
#define OPCODE_HALT	0x1F		//  HALT

#define AMOD_N		0x01		// branch on N
#define AMOD_Z		0x02		// branch on Z
#define AMOD_O		0x03		// branch on O
#define AMOD_C		0x04		// branch on C

#define AMOD_0		0x00		// amod == 000
#define AMOD_1		0x01		// amod == 001
#define AMOD_2		0x02		// amod == 010
#define AMOD_3		0x03		// amod == 011
#define AMOD_4		0x04		// amod == 100
#define AMOD_5		0x05		// amod == 101
#define AMOD_6		0x06		// amod == 110
#define AMOD_7		0x07		// amod == 111



/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 $ 	Typedefs
 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
typedef struct controller_str
{
	uchar curr_state;	// FETCH, DECODE, EXECUTE
	ushort op_code;		// Parsed opcode for use in EXECUTE
	ushort operand_1;	// Parsed operands for use in EXECUTE
	ushort operand_2;
	ushort operand_3;
} ControllerStr;
typedef ControllerStr * Controller;
typedef MemoryModulePtr Memory;	// 'cause I'm tired of typing it.

 /*--------------------------------------------------------------------------------------------------
 -  	Prototypes
 -
 -  	External Operations:
 -	Initialize:  creates controller object with initial state set to FETCH
 - 			and returns a pointer.
 -
 -	Step:	(needs CPU*) evaluates current state, calls the appropriate
 -		function, then advances the controller to the next state.
 -		Checks the CPU's Halt bit before returning to the FETCH state.
 -
 -	Internal Operations:
 -	Fetch:	(needs Internal Registers* and Memory*) retrieves word stored at
 -		location pointed to by the PC, stores it in the IR
 -		register, and increments the PC.
 -
 -	Decode:  (needs IR*) Splits out the opcode portion of the command in
 -		the IR.
 -
 -	Execute:  evaluates the opcode in a switch to execute the command.
 -
 -	Load/Store Operations:
 -	Execute LDI:  parse operands and execute.
 -	Execute LADR:  parse operand and execute.
 -	Execute LDB:  parse operands and execute.
 -	Execute LDW:  parse operands and execute.
 -	Execute STB:  parse operands and execute.
 -	Execute STW:  parse operands and execute.
 -	Execute MOVB:  parse operands and execute.
 -	Execute MOVW:  parse operands and execute.
 -
 -	ALU Operations:
 -	Execute ADDI:  parse operands and execute.
 -	Execute ADD:  parse operands and execute.
 -	Execute SUBI:  parse operands and execute.
 -	Execute SUB:  parse operands and execute.
 -	Execute NEG:  parse operand and execute.
 -	Execute AND:  parse operands and execute.
 -	Execute OR:  parse operands and execute.
 -	Execute NOT:  parse operand and execute.
 -	Execute SHL:  parse operand and execute.
 -	Execute SHR:  parse operand and execute.
 -
 -	Flow of Control Operations:
 -	Execute BR:  parse operand and execute.
 -	Execute BRcc:  parse operand and execute.
 -
 -	I/O Operations:
 -	Execute IN:  parse operand and execute.
 -	Execute OUT:  parse operand and execute.
 -
 --------------------------------------------------------------------------------------------------*/
 Controller controller_initialize(); // initialize controller

 int controller_step(Controller, RegisterFilePtr, ALU, InternalRegisters, Memory);

 int controller_fetch(InternalRegisters, Memory);			// fetch instruction from memory, increment PC
 int controller_decode(Controller, InternalRegisters);		// parse opcode
 int controller_execute(Controller, RegisterFilePtr, ALU, InternalRegisters, Memory);// parse operands, execute operation

 int controller_parseOperands(Controller, InternalRegisters);		// parse operands based on instruction format

 int controller_exec_LDI(Controller, RegisterFilePtr);		// $Rd <- immed7; pad with leading 0s
 int controller_exec_LADR(Controller, RegisterFilePtr, InternalRegisters, Memory);	// $Rd <- M[PC] << 8; $Rd <- M[PC+1]; PC <- PC+2
 int controller_exec_LDB(Controller, RegisterFilePtr, Memory);	// $Rdlow <- M[$Rr] ; only for $R0-$R3 $Rr can be any reg
 int controller_exec_LDW(Controller, RegisterFilePtr, Memory);	// $Rdlow <- M[$Rr], $Rdhigh <- M[$Rr + 1]; any register
 int controller_exec_STB(Controller, RegisterFilePtr, Memory);	// M[$Rr] <- $Rslow
 int controller_exec_STW(Controller, RegisterFilePtr, Memory); 	// M[$Rr] <- $Rslow; M[$Rr + 1] <- $Rshigh
 int controller_exec_MOVB(Controller, RegisterFilePtr);		// $Rdlow <- $Rslow ; only for $R0- $R3
 int controller_exec_MOVW(Controller, RegisterFilePtr);		// $Rd <- $Rs

 int controller_exec_ADDI(Controller, RegisterFilePtr, ALU, InternalRegisters);		// parse operands, load ALU registers and execute.
 int controller_exec_ADD(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_SUBI(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_SUB(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_NEG(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_AND(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_OR(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_NOT(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_SHL(Controller, RegisterFilePtr, ALU, InternalRegisters);
 int controller_exec_SHR(Controller, RegisterFilePtr, ALU, InternalRegisters);

 int controller_exec_BR(Controller, RegisterFilePtr, InternalRegisters);		// PC <- $Rr; branch absolute
 int controller_exec_BRcc(Controller, RegisterFilePtr, InternalRegisters);		// if (cc) PC <- $Rr; else PC unaffected; cc = N, Z, C, O

 int controller_exec_IN(Controller, RegisterFilePtr);	// $R0low <- IO[port#]; if port is write only results are undefined
 int controller_exec_OUT(Controller, RegisterFilePtr);	// IO[port#] <- $R0low; if port is read only results are undefined

 int controller_exec_HALT(InternalRegisters);			// simply sets the CPU halt bit to TRUE




/***************************************************************************************************
 * 	ADT: CPU
 * 	Description:  This is a 'lite' simulation of the CPU of the SC-2.  It encapsulates pointers
 *	to the CPU register file, ALU, Controller, Status Word register, Program Counter register,
 *	Instruction register, and Halt 	bit.
 *
 ***************************************************************************************************/

/*##################################################################################################
 # 	Defines
 ##################################################################################################*/

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 $ 	Typedefs
 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/

typedef struct cpu_str
{
	ALU alu;
	Controller controller;
	RegisterFilePtr reg_file;
	InternalRegisters internal;

} CPUStr;

typedef CPUStr * CPU;

/*--------------------------------------------------------------------------------------------------
 -  	Prototypes
 -
 -	INITIALIZE - allocates struct and registers.
 -
 -	(is we need accessors and mutators for CPU registers, stick 'em here.)
 -
 --------------------------------------------------------------------------------------------------*/
 CPU cpu_initialize();			// initialize CPU and it's registers
 int cpu_tick(CPU, Memory);// triggers the simulation to execute one 'clock cycle'





 // prototypes for unit tests (so I can move them to the bottom of the .c file)
 void registerTest();
 void registerFileTest();
 void memoryTest();
 void ALUTest();
